package com.changyou.kf.mock.socket;

import com.changyou.kf.mock.entity.RoleInfo;
import com.changyou.kf.mock.service.GameLoginService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
public class CustomWebSocketHandler extends TextWebSocketHandler {

    // 用于存储WebSocket会话
    private static final Map<String, WebSocketSession> clientMap = new ConcurrentHashMap<>();

    private static final Map<String, List<String>> userClientsMap = new ConcurrentHashMap<>();

    //https://blog.csdn.net/wlddhj/article/details/141196625?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0-141196625-blog-142983069.235^v43^control&spm=1001.2101.3001.4242.1&utm_relevant_index=3

    @Resource
    private GameLoginService gameLoginService;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String clientId = session.getId();
        clientMap.put(clientId, session);
        log.info("onConnect clientId:`{}`", clientId);

        /*Map<String, String> paramMap = getParamMap(session.getUri().getQuery());
        log.info("onConnect clientId:`{}`,paramMap:{}", clientId, paramMap);
        String appkey = paramMap.get("appkey");
        String channelId = paramMap.get("channelId");
        String serverId = paramMap.get("serverId");
        String secretryRoleId = paramMap.get("secretryRoleId");
        String roleId = paramMap.get("roleId");*/

        String queryParams = session.getUri().getQuery();
        log.info("onConnect clientId:`{}`,queryParams:{}", clientId, queryParams);
        RoleInfo roleInfo = getRoleInfoByParams(queryParams, clientId);

        String user = roleInfo.getRoleId();
        gameLoginService.addRoleInfo(roleInfo);;

        List<String> userClients = userClientsMap.computeIfAbsent(user, k -> new ArrayList<>());
        userClients.add(clientId);
        log.info("userClientMap add user:{},totalSize:{}", user, userClients.size());

        log.info("onConnect clientSize:{},userClientsSize:{}", clientMap.size(), userClientsMap.size());

    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String clientId = session.getId();
        String payload = message.getPayload();
        log.info("onMessage clientId:`{}`, payload:{}", clientId, payload);

        String queryParams = session.getUri().getQuery();
        Map<String, String> paramMap = getParamMap(queryParams);
        String roleId = paramMap.getOrDefault("roleId", "");
        String targetRoleId = paramMap.getOrDefault("targetRoleId", "");
        log.info("onMessage clientId:`{}`,queryParams:{}", clientId, queryParams);
        RoleInfo roleInfo = gameLoginService.getRoleInfo(roleId);
        if (roleInfo == null) {
            session.sendMessage(new TextMessage("<span style='color: red;'>未找到玩家信息</span>"));
            return;
        }
        if (StringUtils.isBlank(targetRoleId)) {
            session.sendMessage(new TextMessage("<span style='color: red;'>私聊目标角色为空</span>"));
            return;
        }
        if (StringUtils.isBlank(payload)) {
            session.sendMessage(new TextMessage("<span style='color: red;'>私聊内容为空</span>"));
            return;
        }

        /*Map<String, String> paramMap = getParamMap(session.getUri().getQuery());
        log.info("onMessage clientId:`{}`,paramMap:{}", clientId, paramMap);
        // 发送回复消息
        String replyMessage = "服务器收到消息:" + payload;
        session.sendMessage(new TextMessage(replyMessage));*/
        gameLoginService.writeChatMessage(roleInfo, payload);
        session.sendMessage(new TextMessage("succ"));

        List<String> targetClients = userClientsMap.get(targetRoleId);
        if (!CollectionUtils.isEmpty(targetClients)) {
            targetClients.stream().forEach(targetClient -> {
                WebSocketSession socketSession = clientMap.get(targetClient);
                if (socketSession != null) {
                    try {
                        socketSession.sendMessage(new TextMessage(String.format("角色ID:%s&nbsp;回复消息:&nbsp;%s", roleId, payload)));
                    } catch (Exception ex) {
                        log.error("handleTextMessage targetRoleId:{} msg send ex:{}",
                                targetRoleId, ex.getMessage(), ex);
                    }
                }
            });
        }

    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        String clientId = session.getId();
        clientMap.remove(clientId);
        log.info("onDisconnect clientId:`{}`", clientId);

        /*Map<String, String> paramMap = getParamMap(session.getUri().getQuery());
        log.info("onDisconnect clientId:`{}`,paramMap:{}", clientId, paramMap);

        String appkey = paramMap.get("appkey");
        String channelId = paramMap.get("channelId");
        String serverId = paramMap.get("serverId");
        String secretryRoleId = paramMap.get("secretryRoleId");
        String roleId = paramMap.get("roleId");*/

        String queryParams = session.getUri().getQuery();
        log.info("onDisconnect clientId:`{}`,queryParams:{}", clientId, queryParams);
        RoleInfo roleInfo = getRoleInfoByParams(queryParams, clientId);

        String user = roleInfo.getRoleId();
        List<String> userClients = userClientsMap.get(user);
        if (!CollectionUtils.isEmpty(userClients)) {
            if (userClients.contains(clientId)) {
                userClients.remove(clientId);
            }
            if (userClients.isEmpty()) {
                userClientsMap.remove(user);
            }
        }
        gameLoginService.removeRoleInfo(user);
        log.info("onDisconnect clientSize:{},userClientsSize:{}", clientMap.size(), userClientsMap.size());
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable throwable) throws Exception {
        String clientId = session.getId();
        log.error("websocket clientId:`{}` transport error:{}", clientId, throwable.getMessage(), throwable);
    }

    // 广播消息给所有连接的客户端
    public void broadcastMessage(String message) {
        clientMap.values().forEach(session -> {
            try {
                session.sendMessage(new TextMessage(message));
            } catch (IOException e) {
                log.error("广播消息失败", e);
            }
        });
    }

    public boolean sendGameChat(String roleId, String message) {
        List<String> clientIds = userClientsMap.get(roleId);
        log.info("sendGameChat roleId:{},clientIds:{},message:{}", roleId, clientIds, message);
        if (CollectionUtils.isEmpty(clientIds)) {
            return false;
        }
        clientIds.stream().forEach(clientId -> {
            WebSocketSession session = clientMap.get(clientId);
            if (session != null) {
                try {
                    session.sendMessage(new TextMessage(message));
                } catch (IOException e) {
                    log.error("发送消息失败", e);
                }
            }
        });
        /*clientMap.values().forEach(session -> {
            try {
                session.sendMessage(new TextMessage(message));
            } catch (IOException e) {
                log.error("广播消息失败", e);
            }
        });*/
        return true;
    }

    /** 将请求参数字符串转换成map */
    private Map<String, String> getParamMap(String queryString) {
        Map<String, String> paramMap = new HashMap<String, String>();
        if (StringUtils.isNotBlank(queryString)) {
            String[] params = queryString.split("&");
            for (String p : params) {
                String[] strs = p.split("=");
                if (strs.length == 2) {
                    paramMap.put(strs[0], strs[1]);
                }
            }
        }
        return paramMap;
    }

    private RoleInfo getRoleInfoByParams(String queryString, String clientId) {
        Map<String, String> paramMap = getParamMap(queryString);
        String appkey = paramMap.getOrDefault("appkey", "");
        String serverId = paramMap.getOrDefault("serverId", "");
        String roleId = paramMap.getOrDefault("roleId", "");
        String roleName = urlDecode(paramMap.getOrDefault("roleName", ""));
        String targetRoleId = urlDecode(paramMap.getOrDefault("targetRoleId", ""));
        RoleInfo roleInfo = RoleInfo.builder()
                .appkey(appkey).serverId(serverId).roleId(roleId)
                .roleName(roleName)
                .targetRoleId(targetRoleId)
                .build();
        return roleInfo;
    }

    public static String urlDecode(String source) {
        if (StringUtils.isBlank(source)) {
            return "";
        }
        try {
            String result = URLDecoder.decode(source, "UTF-8");
            return result;
        } catch (UnsupportedEncodingException e) {
            //ingore ex
        }
        return "";
    }

}
